#include "Model.h"

void VertexRhwInit(Vertex& v) {
	v.rhw = 1 / v.pos.w;
	v.color.x *= v.rhw;
	v.color.y *= v.rhw;
	v.color.z *= v.rhw;
	v.tex.x *= v.rhw;
	v.tex.y *= v.rhw;
	v.normal.x *= v.rhw;
	v.normal.y *= v.rhw;
	v.normal.z *= v.rhw;
}
char *ReadFile(const char* file)
{
	FILE *pFile = fopen(file, "rb");
	if (!pFile) {
		return NULL;
	}

	char *pBuf;
	fseek(pFile, 0, SEEK_END);
	int len = ftell(pFile);
	pBuf = new char[len + 1];
	rewind(pFile);
	fread(pBuf, 1, len, pFile);
	pBuf[len] = '\0';
	fclose(pFile);
	return pBuf;
}
void FixNormal(Vertex& v1, Vertex& v2, Vertex& v3) {
	Vector& p1 = v1.pos;
	Vector& p2 = v2.pos;
	Vector& p3 = v3.pos;

	Vector edge1, edge2, pn;
	edge1 = p2 - p1;
	edge2 = p3 - p2;
	pn = getCrossProduct(edge2, edge1);
	pn.normalize();
	pn.w = 0.f;

	v1.normal = pn / v1.fNum + v1.normal;
	v2.normal = pn / v2.fNum + v2.normal;
	v3.normal = pn / v3.fNum + v3.normal;
}
void FixUv(Vertex& v1, Vertex& v2, Vertex& v3) {
	v1.tex.x = 0; v1.tex.y = 0;
	v2.tex.x = 0; v2.tex.y = 0;
	v3.tex.x = 0; v3.tex.y = 0;
}

Model::Model(const char *file, Device *dv) {
	this->file = file;
	this->device = dv;
	loadMesh();
}
void Model::loadMesh() {
	char* pFile;
	pFile = ReadFile(file);
	if (!pFile) {
		return;
	}

	char* pSrc;
	pSrc = pFile;

	int i, vc, fc;

	i = 0, vc = 0, fc = 0;
	char line[1024];
	memset(line, 0, 1024);
	for (; *pSrc != '\0';) {
		if (*pSrc == '\n') {
			if (line[0] == 'v') {
				++vc;
			}
			else if (line[0] == 'f') {
				++fc;
			}

			i = 0;
			memset(line, 0, 1024);
		}
		else {
			if (i > 1024) {
				delete pFile;
				return;
			}
			line[i++] = *pSrc;
		}
		++pSrc;
	}
	if (vc == 0 || fc == 0) {
		delete pFile;
		return;
	}

	vsize = vc; fsize = fc;
	pVertexs = new Vertex[vc];
	pFaces = new Face[fc];

	pSrc = pFile;

	i = 0, vc = 0, fc = 0;
	memset(line, 0, 1024);
	for (; *pSrc != '\0';) {
		if (*pSrc == '\n') {
			if (line[0] == 'v') {
				float x, y, z;
				sscanf(line, "v %f %f %f", &x, &y, &z);
				pVertexs[vc].pos = Vector(x, y, z, 1);
				pVertexs[vc].color = Vector(1, 0, 0);
				pVertexs[vc].tex = Vector(0, 1, 0);
				pVertexs[vc].normal = Vector(0, 0, 0);
				pVertexs[vc].rhw = 1;
				VertexRhwInit(pVertexs[vc]);
				vc++;
			}
			else if (line[0] == 'f') {
				int p1, p2, p3;
				sscanf(line, "f %d %d %d", &p1, &p2, &p3);
				pFaces[fc].i1 = p1 - 1;
				pVertexs[p1 - 1].fNum += 1;
				pFaces[fc].i2 = p2 - 1;
				pVertexs[p2 - 1].fNum += 1;
				pFaces[fc].i3 = p3 - 1;
				pVertexs[p3 - 1].fNum += 1;
				fc++;
			}

			i = 0;
			memset(line, 0, 1024);
		}
		else {
			line[i++] = *pSrc;
		}
		++pSrc;
	}
	delete pFile;
	return;
}
void Model::Draw() {
	for (int i = 0; i < fsize; i++) {
		int i1 = pFaces[i].i1;
		int i2 = pFaces[i].i2;
		int i3 = pFaces[i].i3;

		FixNormal(pVertexs[i1], pVertexs[i2], pVertexs[i3]);
	}
	//Test
	/*int i1 = pFaces[10].i1;
	int i2 = pFaces[10].i2;
	int i3 = pFaces[10].i3;

	Vertex v1 = pVertexs[i1];
	Vertex v2 = pVertexs[i2];
	Vertex v3 = pVertexs[i3];
	v1.normal.normalize();
	v2.normal.normalize();
	v3.normal.normalize();
	device->drawTriangleFill(v1, v2, v3);*/

	for (int i = 0; i < fsize; i++) {
		int i1 = pFaces[i].i1;
		int i2 = pFaces[i].i2;
		int i3 = pFaces[i].i3;

		Vertex v1 = pVertexs[i1];
		Vertex v2 = pVertexs[i2];
		Vertex v3 = pVertexs[i3];
		v1.normal.normalize();
		v2.normal.normalize();
		v3.normal.normalize();
		device->drawTriangleFill(v1, v2, v3);
	}
}
